package com.such.kit.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.such.kit.stream.StreamCommons;
import com.such.kit.string.StringCommons;
import com.such.kit.validate.ValidateCommons;

/**
 * @作者 SUCH
 * @日期 2017-2-28 下午7:20:32
 * @描述 文件分割合并工具类
 */
public class FileSplitAndMerge {

	private static final String SPLIT_PART = ".part";
	
	private static byte[] byteBuffer = new byte[1024];

	/**
	 * <p>方法名：split</p>
	 * <p>描述：分割文件</p>
	 * @param filePath 文件路径
	 * @param targetPath 将文件分割到路径
	 * @param fragmentSize 文件片段大小（KB）
	 * @throws IOException 
	 */
	public static void split(String filePath, String targetPath, long fragmentSize) 
			throws IOException {
		if (ValidateCommons.isNotEmpty(filePath) && ValidateCommons.isNotEmpty(targetPath) && fragmentSize > 0) {
			fragmentSize = fragmentSize * byteBuffer.length;
			File file = new File(filePath);
			if (file.exists()) {
				long fileSize = file.length();
				long fragmentCount = 0;
				if (fileSize % fragmentSize == 0) {
					fragmentCount = fileSize / fragmentSize;
				} else {
					fragmentCount = (fileSize / fragmentSize) + 1;
				}
				String fileName = file.getName();
				FileCommons.createFolder(targetPath);
				BufferedInputStream bufIn = null;
				BufferedOutputStream bufOut = null;
				try {
					FileInputStream fileIn = new FileInputStream(file);
					bufIn = new BufferedInputStream(fileIn);
					for (long l = 0; l < fragmentCount; l++) {
						String tempFilePath = FileCommons.appendPathNode(targetPath, StringCommons.merger(fileName, SPLIT_PART, l));
						FileOutputStream fileOut = new FileOutputStream(tempFilePath);
						bufOut = new BufferedOutputStream(fileOut);
						int index = 0;
						int sum = 0;
						while ((index = bufIn.read(byteBuffer)) != -1) {
							sum += index;
							bufOut.write(byteBuffer, 0, index);
							bufOut.flush();
							if (sum >= fragmentSize) {
								break;
							}
						}
					}
				} finally {
					byteBuffer = new byte[1024];
					StreamCommons.close(bufIn);
					StreamCommons.close(bufOut);
				}
			}
		}
	}

	/**
	 * <p>方法名：merge</p>
	 * <p>描述：合并分割的文件</p>
	 * @param path 文件夹路径
	 * @param flieNamePrefix 文件前缀
	 * @param targetPath 将文件合并到路径
	 * @throws IOException 
	 */
	public static void merge(String path, String flieNamePrefix, String targetPath) 
			throws IOException {
		if (ValidateCommons.isNotEmpty(path) && ValidateCommons.isNotEmpty(flieNamePrefix) && ValidateCommons.isNotEmpty(targetPath)) {
			File file = new File(path);
			if (file.exists() && file.isDirectory()) {
				FileCommons.createFolder(targetPath);
				BufferedInputStream bufIn = null;
				BufferedOutputStream bufOut = null;
				try {
					List<File> fileList = new ArrayList<File>();
					File[] files = file.listFiles();
					if (ValidateCommons.isNotEmpty(files)) {
						for (File tempFile : files) {
							String tempFileName = tempFile.getName();
							if (tempFileName.startsWith(flieNamePrefix)) {
								fileList.add(tempFile);
							}
						}
					}
					String fileName = flieNamePrefix;
					int tempIndex = flieNamePrefix.lastIndexOf(SPLIT_PART);
					if (tempIndex > -1) {
						fileName = flieNamePrefix.substring(0, tempIndex);
					}
					targetPath = FileCommons.appendPathNode(targetPath, fileName);
					FileOutputStream fileOut = new FileOutputStream(targetPath);
					bufOut = new BufferedOutputStream(fileOut);
					for (File tempFile : fileList) {
						FileInputStream fileIn = new FileInputStream(tempFile);
						bufIn = new BufferedInputStream(fileIn);
						int index = 0;
						while ((index = bufIn.read(byteBuffer)) != -1) {
							bufOut.write(byteBuffer, 0, index);
							bufOut.flush();
						}
					}
				} finally {
					byteBuffer = new byte[1024];
					StreamCommons.close(bufIn);
					StreamCommons.close(bufOut);
				}
			}
		}
	}
	
}
